cmake_minimum_required(VERSION 3.8)

# # 编译器设置 - 必须在project()之前设置
# if(NOT DEFINED CMAKE_C_COMPILER)
#     set(CMAKE_C_COMPILER /usr/bin/gcc)
# endif()
# if(NOT DEFINED CMAKE_CXX_COMPILER)
#     set(CMAKE_CXX_COMPILER /usr/bin/g++)
# endif()

project(try_asio)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(EXPORT_COMPILE_COMMANDS ON)
add_custom_target(COPY_COMPILE_COMMANDS
    COMMAND cp ${CMAKE_BINARY_DIR}/compile_commands.json ${CMAKE_CURRENT_SOURCE_DIR}/compile_commands.json
)

find_package(Threads REQUIRED)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(TargetUtils)
include(CCache)
include(Protobuf)
include(FlatBuffers)

setup_ccache()
reset_ccache_stats()

# 设置protobuf和flatbuffers
setup_protobuf()
generate_protobuf_files()
setup_flatbuffers()
generate_flatbuffers_files()

# 获取protobuf和flatbuffers包含目录
get_protobuf_include_dirs(PROTOBUF_INCLUDE_DIRS)
get_flatbuffers_include_dirs(FLATBUFFERS_INCLUDE_DIRS)

set(COMMON_INCLUDE_DIRS
    include
    third_party/boost.asio/include
    third_party/fmt/include
    third_party/spdlog/include
    ${PROTOBUF_INCLUDE_DIRS}
    ${FLATBUFFERS_INCLUDE_DIRS}
)

set(COMMON_COMPILE_DEFS
    BOOST_ASIO_HEADER_ONLY=1
    BOOST_ASIO_NO_DEPRECATED=0
    BOOST_ASIO_DISABLE_BOOST_DATE_TIME=1
)

# 获取protobuf和flatbuffers依赖
get_protobuf_deps(PROTOBUF_DEPS)
get_flatbuffers_deps(FLATBUFFERS_DEPS)

set(COMMON_PRIVATE_DEPS
    Threads::Threads
    fmt::fmt
    spdlog::spdlog
    ${PROTOBUF_DEPS}
    ${FLATBUFFERS_DEPS}
)



########################### JetComm ###########################
set(JetCommon_INCLUDE_DIRS
    include
)

file(GLOB_RECURSE JetCommon_SOURCE src/*.cc src/*.cpp)
list(REMOVE_ITEM JetCommon_SOURCE src/comm_main.cpp)

# 添加protobuf生成的源文件
if(PROTOBUF_ENABLED)
    list(APPEND JetCommon_SOURCE ${PROTOBUF_GENERATED_SRCS})
endif()

message("JetCommon_SOURCE ${JetCommon_SOURCE}")

add_library(jet_comm STATIC ${JetCommon_SOURCE})
configure_target(jet_comm
    PRIVATE_DEPS ${COMMON_PRIVATE_DEPS}
    PRIVATE_INCLUDE_DIRECTORIES ${JetCommon_INCLUDE_DIRS} ${COMMON_INCLUDE_DIRS}
    PRIVATE_COMPILE_DEFINITIONS ${COMMON_COMPILE_DEFS}
)

# 添加protobuf和flatbuffers支持
add_protobuf_to_target(jet_comm)
add_flatbuffers_to_target(jet_comm)

# 创建共享库变量（与静态库相同的源文件）
set(JetCommon_SHARED_SOURCE ${JetCommon_SOURCE})
add_library(jet_comm_shared SHARED ${JetCommon_SHARED_SOURCE})
configure_target(jet_comm_shared
    PRIVATE_DEPS ${COMMON_PRIVATE_DEPS}
    PRIVATE_INCLUDE_DIRECTORIES ${JetCommon_INCLUDE_DIRS} ${COMMON_INCLUDE_DIRS}
    PRIVATE_COMPILE_DEFINITIONS ${COMMON_COMPILE_DEFS}
)

# 添加protobuf和flatbuffers支持
add_protobuf_to_target(jet_comm_shared)
add_flatbuffers_to_target(jet_comm_shared)

set_target_properties(jet_comm_shared PROPERTIES POSITION_INDEPENDENT_CODE ON)

add_executable(comm_main src/comm_main.cpp)
configure_target(comm_main
    PRIVATE_DEPS ${COMMON_PRIVATE_DEPS} jet_comm
    PRIVATE_INCLUDE_DIRECTORIES ${JetCommon_INCLUDE_DIRS} ${COMMON_INCLUDE_DIRS}
    PRIVATE_COMPILE_DEFINITIONS ${COMMON_COMPILE_DEFS}
)

########################### DEMOS ###########################

set(DEMOS_INCLUDE_DIRS
    demos/
)

# executable list
set(DEMOS_TARGET_LIST
        demos/basic_example
        demos/debug_example
        demos/fmt_spdlog_example
        demos/block_timer
        demos/async_timer
        demos/tcp_time_client
        demos/tcp_time_server
        demos/multi_thread_strand
        demos/member_function_handler
        demos/async_tcp_time_server
        demos/async_tcp_time_client
        demos/eventfd_basic_example
        demos/eventfd_producer_consumer
        demos/eventfd_cross_process
        demos/eventfd_shared_registry
        # demos/eventfd_internals_explanation
        demos/descriptor_types_overview
        demos/debug_eventfd_issue
        demos/improved_pubsub_demo
        demos/eventfd_transfer_examples
)

# 添加protobuf和flatbuffers demo
if(PROTOBUF_ENABLED)
    list(APPEND DEMOS_TARGET_LIST "demos/protobuf_serializer_test")
    message(STATUS "已添加protobuf demo到构建列表")
endif()

if(FLATBUFFERS_ENABLED)
    list(APPEND DEMOS_TARGET_LIST "demos/flatbuffer_struct_demo")
    list(APPEND DEMOS_TARGET_LIST "demos/pod_characteristics_test")
    message(STATUS "已添加flatbuffer demo到构建列表")
endif()

# build demos 
foreach(source_path ${DEMOS_TARGET_LIST})
    message("source_path ${source_path}")
    string(REPLACE "/" "_" target_name ${source_path})
    message("target_name ${target_name}")
    add_executable(${target_name} ${source_path}.cpp)
    set(CUSTOM_DEPS "jet_comm")
    set(CUSTOM_INCS "${JetCommon_INCLUDE_DIRS}")


    configure_target(${target_name}
        PRIVATE_DEPS ${COMMON_PRIVATE_DEPS} ${CUSTOM_DEPS}
        PRIVATE_INCLUDE_DIRECTORIES ${DEMOS_INCLUDE_DIRS} ${COMMON_INCLUDE_DIRS} ${CUSTOM_INCS}
        PRIVATE_COMPILE_DEFINITIONS ${COMMON_COMPILE_DEFS}
    )
    
    # 检查是否需要protobuf支持
    target_needs_protobuf(${target_name} NEEDS_PROTOBUF)
    if(NEEDS_PROTOBUF)
        add_protobuf_to_target(${target_name})
    endif()
    
    # 检查是否需要flatbuffers支持
    target_needs_flatbuffers(${target_name} NEEDS_FLATBUFFERS)
    if(NEEDS_FLATBUFFERS)
        add_flatbuffers_to_target(${target_name})
    endif()
endforeach()

########################### LIBRARIES ###########################

##### ! boost_asio library #####
# 创建 boost_asio 库
add_library(boost_asio
    third_party/boost.asio/include/boost/asio/impl/src.hpp
)

# 设置 boost_asio 库属性
target_include_directories(boost_asio PUBLIC 
    third_party/boost.asio/include
)

# 设置编译定义
target_compile_definitions(boost_asio PUBLIC
    BOOST_ASIO_SEPARATE_COMPILATION=1
    BOOST_ASIO_NO_DEPRECATED=0
    BOOST_ASIO_DISABLE_BOOST_DATE_TIME=1
)

# 设置 C++ 标准
target_compile_features(boost_asio PUBLIC cxx_std_17)

# 明确指定为 C++ 库
set_target_properties(boost_asio PROPERTIES
    LINKER_LANGUAGE CXX
)

# 创建别名目标
add_library(Boost::asio ALIAS boost_asio)

##### ! fmt library #####
# 添加fmt库前设置PIC选项
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(third_party/fmt)

##### ! spdlog library #####
# 添加spdlog库前设置PIC选项
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_subdirectory(third_party/spdlog)

########################### ccache statistics ###########################
print_ccache_usage_tips()

if(USE_CCACHE AND CCACHE_STATS AND CCACHE_PROGRAM)
    add_custom_target(ccache_final_stats ALL
        COMMAND ${CMAKE_COMMAND} -E echo ""
        COMMAND ${CMAKE_COMMAND} -E echo "=== ccache 编译统计报告 ==="
        COMMAND ${CCACHE_PROGRAM} -s
        COMMAND ${CMAKE_COMMAND} -E echo "============================="
        COMMAND ${CMAKE_COMMAND} -E echo ""
        COMMENT "show ccache final statistics"
    )
    
    set(CCACHE_DEPS 
        jet_comm 
        jet_comm_shared 
        comm_main 
        boost_asio
        fmt
        spdlog
    )
    
    # 添加protobuf和flatbuffers生成目标
    if(PROTOBUF_ENABLED AND PROTOBUF_GENERATED_TARGET)
        list(APPEND CCACHE_DEPS ${PROTOBUF_GENERATED_TARGET})
    endif()
    
    if(FLATBUFFERS_ENABLED AND FLATBUFFERS_GENERATED_TARGET)
        list(APPEND CCACHE_DEPS ${FLATBUFFERS_GENERATED_TARGET})
    endif()
    
    add_dependencies(ccache_final_stats ${CCACHE_DEPS})
    
    foreach(source_path ${DEMOS_TARGET_LIST})
        string(REPLACE "/" "_" target_name ${source_path})
        add_dependencies(ccache_final_stats ${target_name})
    endforeach()
    
    set_target_properties(ccache_final_stats PROPERTIES
        EXCLUDE_FROM_ALL FALSE
    )
endif()